package com.keyue.common.utils;

import com.keyue.config.MinioConfig;
import io.minio.*;
import io.minio.errors.ErrorResponseException;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.Nullable;
import org.springframework.web.multipart.MultipartFile;

import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;

/**
 * @author: xms
 * @description: 阿里oss图片存储工具类
 * @date: 2023/10/30 18:24
 * @version: 1.0
 */
@Slf4j
public class MinIOUtil {

    /**
     * minio 客户端
     */
    public static MinioClient minioClient;


    static {
        minioClient = MinioClient.builder()
                .endpoint(MinioConfig.ENDPOINT)
                .credentials(MinioConfig.ACCESS_KEY, MinioConfig.SECRET_KEY)
                .build();
    }

    /**
     * 检查存储桶是否存在
     *
     * @param bucketName 存储桶名称
     * @return 存储桶是否存在 状态码 true:存在 false:不存在
     */
    public static boolean bucketExists(String bucketName) throws Exception {
        return !minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
    }

    /**
     * 创建存储桶
     */
    public static void makeBucket(String bucketName) throws Exception {
        if (bucketExists(bucketName)) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }
    }

    /**
     * 列出所有存储桶
     */
    public static List<Bucket> listBuckets() throws Exception {
        return minioClient.listBuckets();
    }

    /**
     * 上传文件
     *
     * @param file       文件
     * @param bucketName 存储桶名称
     * @param rename     是否重命名
     */
    public static String uploadFile(MultipartFile file, String bucketName, boolean rename) throws Exception {
        // 如果未指定bucketName，使用默认的
        bucketName = getBucketName(bucketName);

        // 检查存储桶是否存在，不存在则创建
        ensureBucketExists(bucketName);

        // 生成唯一文件名
        String objectName = generateObjectName(file, rename);
        // 上传文件
        minioClient.putObject(
                PutObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .stream(file.getInputStream(), file.getSize(), -1)
                        .contentType(file.getContentType())
                        .build());
        return objectName;
    }

    /**
     * 上传文件
     *
     * @param file
     * @param bucketName
     * @return
     * @throws Exception
     */
    public static String uploadFile(MultipartFile file, String bucketName) throws Exception {
        String objectName = uploadFile(file, bucketName, false);
        return getFileUrl(objectName, bucketName);
    }

    /**
     * 上传文件
     *
     * @param file
     * @return
     * @throws Exception
     */
    public static String uploadFile(MultipartFile file) throws Exception {
        String objectName = uploadFile(file, null, false);
        return getFileUrl(objectName, null);
    }


    /**
     * 下载文件
     */
    public static InputStream downloadFile(String objectName, String bucketName) throws Exception {
        return minioClient.getObject(
                GetObjectArgs.builder()
                        .bucket(getBucketName(bucketName))
                        .object(objectName)
                        .build());
    }

    /**
     * 删除文件
     */
    public static void removeFile(String objectName, String bucketName) throws Exception {
        minioClient.removeObject(
                RemoveObjectArgs.builder()
                        .bucket(getBucketName(bucketName))
                        .object(objectName)
                        .build());
    }

    /**
     * 获取文件URL（先检查文件是否存在）
     */
    public static String getFileUrl(String objectName, String bucketName) throws Exception {
        try {
            minioClient.statObject(
                    StatObjectArgs.builder()
                            .bucket(getBucketName(bucketName))
                            .object(objectName)
                            .build());
        } catch (ErrorResponseException e) {
            // 文件不存在时抛出异常
            throw new FileNotFoundException("File not found: " + objectName);
        }

        // 文件存在，生成URL
        return minioClient.getPresignedObjectUrl(
                GetPresignedObjectUrlArgs.builder()
                        .method(Method.GET)
                        .bucket(getBucketName(bucketName))
                        .object(objectName)
                        .build());
    }

    /**
     * 生成唯一文件名
     */
    public static @Nullable String generateObjectName(MultipartFile file, boolean rename) {
        String fileName = file.getOriginalFilename();
        String objectName = fileName;
        if (rename && fileName != null) {
            objectName = UUID.randomUUID().toString().replaceAll("-", "")
                    + fileName.substring(fileName.lastIndexOf("."));
        }
        return objectName;
    }

    /**
     * 检查存储桶是否存在，不存在则创建
     */
    public static void ensureBucketExists(String bucketName) throws Exception {
        if (bucketExists(bucketName)) {
            makeBucket(bucketName);
        }
    }

    /**
     * 获取存储桶名称
     */
    public static String getBucketName(String bucketName) {
        if (bucketName == null || bucketName.isEmpty()) {
            bucketName = MinioConfig.BUCKET_NAME;
        }
        return bucketName;
    }

}